/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mygameframework.test;

import com.mygameframework.util.Utility;
import com.mygameframework.core.GameCore;
import com.mygameframework.core.GeneralGameCore;
import com.mygameframework.core.input.GameAction;
import com.mygameframework.core.input.InputManager;
import com.mygameframework.scenes.CommonScene;
import com.mygameframework.isoengine.TileSet;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.EnumSet;
import java.util.Random;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/**
 * 已过期
 * @author bill
 */
public class StaggeredMapScene  extends CommonScene{
    
    GameAction NORTH;
    GameAction EAST;
    GameAction SOUTH;
    GameAction WEST;
    GameAction SPACE;
    
    int tw,th;
    int mapWidth;
    int mapHeight;
    int screenWidth;
    int screenHeight;
    int dx,dy;
    Rectangle screenSpace;
    Rectangle anchorSpace;
    Rectangle worldSpace;
    Point screenAnchor=new Point();
    Point cursorAnchor=new Point();
    Point screenAnchorScroll=new Point();
    Insets in;
    
    int Scroll_WHEN_BORDER_SIZE=20;
    
  /** Scroll increment. */
  private static final int SCROLL_INCREMENT_PER_SECOND = 360;
  
    TileSet tileSet;
    TileSet cursor;

    int[][] mapArr;
    MouseMap mmp;
    public StaggeredMapScene(GeneralGameCore gameCore) {
        super(gameCore);
    }
    public static Point stagMap_TileWalker(Point pStart,Direction dir){
        Point tmp=new Point(pStart);
        switch (dir) {
            case NORTH:
                tmp.y-=2;
                break;
            case NORTHEAST:
                tmp.x+=(pStart.y&1);
                tmp.y--;
                break;
            case EAST:
                tmp.x++;
                break;
            case SOUTHEAST:
                tmp.y++;
                tmp.x+=(pStart.y&1);
                break;
            case SOUTH:
                tmp.y+=2;
                break;
            case SOUTHWEST:
                tmp.x+=((pStart.y&1)-1);
                tmp.y++;
                break;
            case WEST:
                tmp.x--;
                break;
            case NORTHWEST:
                tmp.y--;
                tmp.x+=((pStart.y&1)-1);
                break;
            default:
                throw new AssertionError();
        }
        return tmp;
    }

    /**move cursor point (map坐标)*/
    public void moveCursor(Direction dir){
        Point ptTmp=stagMap_TileWalker(this.cursorAnchor,dir);
        //map bounds checks
        if(ptTmp.x<0 ||ptTmp.y<0 || ptTmp.x>(mapWidth-1) || ptTmp.y>(mapHeight-1)) 
            ptTmp=this.cursorAnchor;
        this.cursorAnchor=ptTmp;
        
        Point ptPlot=stagMap_TilePlotter(ptTmp, tw, th, dx, dy);
        screenAnchor.x=(int) (ptPlot.x-screenSpace.getWidth()/2+tw/2);
        screenAnchor.y=(int) (ptPlot.y-screenSpace.getHeight()/2+th/2);
        
        //bounds checking for anchor
        checkScreenAnchor();
    }
    /** a assistant fundation ,map to world */
    public static Point stagMap_TilePlotter(Point map,int tw,int th,int offsetx,int offsety){
        Point result=new Point();
	result.x=map.x*tw+ (map.y&1)*(tw/2);
	result.y=map.y*(th/2);
        
        result.y+=offsety;
        result.x+=offsetx;
	//return calculate point
	return result;
    }

    @Override
    public synchronized void mouseMoved(MouseEvent e) {

        //ptMouse 含有inset的值,
//        Point ptMouse=this.gameCore.getInputManager().getMousePosition();
        Point ptMouse=e.getPoint();
        //通过减insets值,得出相对于窗体内容面板的坐标
    //            ptMouse.x-=in.left;
    //            ptMouse.y-=in.top;

        Point ptMap=slideMap_MouseMapper(ptMouse, mmp,in.left,in.top);
        if(ptMap.x<0) ptMap.x=0;
        if(ptMap.y<0) ptMap.y=0;
        if(ptMap.x>mapWidth-1) ptMap.x=mapWidth-1;
        if(ptMap.y>mapHeight-1) ptMap.y=mapHeight-1;
        System.out.println("final2 map "+ptMap);
        this.cursorAnchor=ptMap;
        ptMouse=e.getPoint();
        screenAnchorScroll.x=0;
        screenAnchorScroll.y=0;
//        System.out.println("ptMouse "+ptMouse);
        if(ptMouse.x<in.left+Scroll_WHEN_BORDER_SIZE){
            screenAnchorScroll.x = -(in.left+ Scroll_WHEN_BORDER_SIZE - ptMouse.x);
        }
        if(ptMouse.y<in.top+Scroll_WHEN_BORDER_SIZE){
            screenAnchorScroll.y = -((in.top+Scroll_WHEN_BORDER_SIZE )-ptMouse.y );
        }
        if(ptMouse.x>screenSpace.getWidth()-Scroll_WHEN_BORDER_SIZE){
            screenAnchorScroll.x = (int) (ptMouse.x-(screenSpace.getWidth()-Scroll_WHEN_BORDER_SIZE));
        }
        if(ptMouse.y>screenSpace.getHeight()-Scroll_WHEN_BORDER_SIZE){
            screenAnchorScroll.y= (int) (ptMouse.y-(screenSpace.getHeight()-Scroll_WHEN_BORDER_SIZE));
        }

    }

    public class MouseMap{
        Dimension m;//存了宽 高 五色图的
        Point refPt;//MAP(0,0) 对应的ptPlot
        Direction[] mouseMapLookup;
    }
    public void loadMouseMap(MouseMap mmp,String path) throws IOException{
        BufferedImage img=Utility.loadBufferedImage(path);
        int w=img.getWidth();
        int h=img.getHeight();
        mmp.m=new Dimension(w, h);
        stagMap_TilePlotter(new Point(0, 0), tw, th, tw, tw);
        mmp.mouseMapLookup=new Direction[w*h];
        int crNW=img.getRGB(0, 0);
        int crNE=img.getRGB(w-1, 0);
        int crSE=img.getRGB(w-1, h-1);
        int crSW=img.getRGB(0, h-1);
        int crtest;
        for(int y=0;y<h;y++){
            for(int x=0;x<w;x++){
                crtest=img.getRGB(x, y);
                mmp.mouseMapLookup[x+w*y]=Direction.CENTER;

                if(crtest ==crNW){
                    mmp.mouseMapLookup[x+w*y]=Direction.NORTHWEST;
                }
                if (crtest == crNE) {
                    mmp.mouseMapLookup[x + y *w] =Direction.NORTHEAST;
                }
                if (crtest == crSW) {
                    mmp.mouseMapLookup[x + y *w] =Direction.SOUTHWEST;
                }
                if (crtest == crSE) {
                    mmp.mouseMapLookup[x + y *w] =Direction.SOUTHEAST;
                }
                
            }
        }
        
        
    }
    /***
     * 
     * @param ptMouse 鼠标在窗体上的坐标(即含有tile bar 和边框)
     * @param mmp 五色图的包装类
     * @return 
     */
    public Point slideMap_MouseMapper(Point ptMouse,MouseMap mmp,int dx,int dy){
        
            //得出鼠标world坐标  //step1 s->w
            ptMouse.x-=dx;
            ptMouse.y-=dy;
            ptMouse.x+=screenAnchor.x;
            ptMouse.y+=screenAnchor.y;
//            System.out.println("p "+ptMouse);
//            step2
            Point ptMap0=new Point(0,0);
            Point ptPlot=stagMap_TilePlotter(ptMap0, tw, th,0,0);
            ptPlot.x+=tileSet.getInfos()[0].dstExt.x;//可忽略
            ptPlot.y+=tileSet.getInfos()[0].dstExt.y;//可忽略
//            System.out.println("ptPlot "+ptPlot);
            ptMouse.x-=ptPlot.x;
            ptMouse.y-=ptPlot.y;
        
//        ptMouse.x -= mmp.refPt.x;
//        ptMouse.y -= mmp.refPt.y;
        //step3
        Point ptMouseMapCoarse = new Point();
        ptMouseMapCoarse.x = ptMouse.x / mmp.m.width;
        ptMouseMapCoarse.y = ptMouse.y / mmp.m.height;
        Point ptMouseMapFine = new Point();
        ptMouseMapFine.x = ptMouse.x % mmp.m.width;
        ptMouseMapFine.y = ptMouse.y % mmp.m.height;
        System.out.println("");
//        System.out.println(ptMouse.y +" /"+mmp.m.height);
        if (ptMouseMapFine.x < 0) { //余数小于0
            ptMouseMapFine.x += mmp.m.width;//加五色图的宽
            ptMouseMapCoarse.x--;
        }
        if (ptMouseMapFine.y < 0) {//余数小于0
            ptMouseMapFine.y += mmp.m.height;//加五色图的高
            ptMouseMapCoarse.y--;
        }
        System.out.println("ptMouseMapCoarse " + ptMouseMapCoarse);
        System.out.println("ptMouseMapFine " + ptMouseMapFine);
        
        Point ptMap = new Point(0, 0);
        while (ptMouseMapCoarse.y > 0) {
            ptMouseMapCoarse.y--;
            ptMap=stagMap_TileWalker(ptMap, Direction.SOUTH);
        }
        while (ptMouseMapCoarse.y < 0) {
            ptMouseMapCoarse.y++;
            ptMap=stagMap_TileWalker(ptMap, Direction.NORTH);
        }
        while (ptMouseMapCoarse.x > 0) {
            ptMouseMapCoarse.x--;
            ptMap=stagMap_TileWalker(ptMap, Direction.EAST);
        }
        while (ptMouseMapCoarse.x < 0) {
            ptMouseMapCoarse.x++;
            ptMap=stagMap_TileWalker(ptMap, Direction.WEST);
        }
        System.out.println("ptMap "+ptMap);
        Direction d =
                mmp.mouseMapLookup[ptMouseMapFine.x+mmp.m.width*ptMouseMapFine.y];
        System.out.println("d "+d);
        switch (d) {
            case CENTER:
                //DO NOTHING
                break;
            case NORTHWEST:
                ptMap=stagMap_TileWalker(ptMap, Direction.NORTHWEST);
                break;
            case NORTHEAST:
                ptMap=stagMap_TileWalker(ptMap, Direction.NORTHEAST);
                break;
            case SOUTHEAST:
                ptMap=stagMap_TileWalker(ptMap, Direction.SOUTHEAST);
                break;
            case SOUTHWEST:
                ptMap=stagMap_TileWalker(ptMap, Direction.SOUTHWEST);
                break;
            default:
                throw new AssertionError();
        }//end switch
        System.out.println("final map "+ptMap);
        return ptMap;          
    }
    public void setupMap(){
        mapArr=new int[mapWidth][mapHeight];
        Random rnd=new Random();
        for(int x=0;x<mapWidth;x++){
            for(int y=0;y<mapHeight;y++){
                mapArr[x][y]=rnd.nextInt(tileSet.getTileCount());
            }
        }
    }
    public void updateSpaces(){
        
        in=this.gameCore.getFrame().getInsets();
        this.screenWidth=this.gameCore.getFrame().getWidth()-in.left-in.right;
        this.screenHeight=this.gameCore.getFrame().getHeight()-in.top-in.bottom;
        dx=in.left;dy=in.top;
        //screen spce
        screenSpace=new Rectangle(dx, dy,
                this.screenWidth,
                this.screenHeight);
                int tw=tileSet.tileInfos[0].src.width;
        int th=tileSet.tileInfos[0].src.height;
        Rectangle t1=(Rectangle) tileSet.tileInfos[0].dstExt.clone();
	Rectangle t2=(Rectangle) tileSet.tileInfos[0].dstExt.clone();
	Point plot;
        Point map=new Point(0, 0);
        plot=stagMap_TilePlotter(map,tw,th,0,0);
        t1.translate(plot.x, plot.y);
        map=new Point(this.mapWidth-1, this.mapHeight-1);
        plot=stagMap_TilePlotter(map,tw,th,0,0);
        t2.translate(plot.x, plot.y);
        //world space
        worldSpace=t1.union(t2);
        //anchor space
        anchorSpace=(Rectangle) worldSpace.clone();
//        anchorSpace.width-=screenSpace.width;
//        anchorSpace.height-=screenSpace.height;
        if (worldSpace.width > screenSpace.width) {
            anchorSpace.width -= screenSpace.width;
        } else {//当地图小于屏幕时,居中
            anchorSpace.width = 0;
            anchorSpace.x=-(screenSpace.width/2-worldSpace.width/2);
        }
        if (worldSpace.height > screenSpace.height) {
            anchorSpace.height -= screenSpace.height;
        } else {//当地图小于屏幕时,居中
            anchorSpace.height = 0;
            anchorSpace.y=-(screenSpace.height/2-worldSpace.height/2);
        }
    }

    @Override
    public void enterFullScreen() {
        updateSpaces();
        System.out.println("enter update "+screenSpace);
    }

    @Override
    public void exitFullScreen() {
        updateSpaces();
        System.out.println("exit update "+screenSpace);
    }
    
    public void setupSpaces(){
        in=this.gameCore.getFrame().getInsets();
        this.screenWidth=this.gameCore.getFrame().getWidth()-in.left-in.right;
        this.screenHeight=this.gameCore.getFrame().getHeight()-in.top-in.bottom;
        dx=in.left;dy=in.top;
        //screen spce
        screenSpace=new Rectangle(dx, dy,
                this.screenWidth,
                this.screenHeight);
        
        Frame f=gameCore.getFrame();
        if( f instanceof JFrame){
        JFrame jf=(JFrame) f;
        System.out.println(" "+jf.getRootPane());
        }
        JPanel panel=new JPanel();
        gameCore.getFrame().add(panel);
        
        System.out.println("fw "+this.gameCore.getFrame().getWidth());
        System.out.println("fh "+this.gameCore.getFrame().getHeight());
        System.out.println("screenspace "+screenSpace);
        System.out.println("in "+in);
        
        int tw=tileSet.tileInfos[0].src.width;
        int th=tileSet.tileInfos[0].src.height;
        Rectangle t1=(Rectangle) tileSet.tileInfos[0].dstExt.clone();
	Rectangle t2=(Rectangle) tileSet.tileInfos[0].dstExt.clone();
	Point plot;
        Point map=new Point(0, 0);
        //attention, worldspace calculating couldnt use dx,dy
        plot=stagMap_TilePlotter(map,tw,th,0,0);
        t1.translate(plot.x, plot.y);
        map=new Point(this.mapWidth-1, this.mapHeight-1);
        plot=stagMap_TilePlotter(map,tw,th,0,0);
        t2.translate(plot.x, plot.y);
        //world space
        worldSpace=t1.union(t2);
        //anchor space
        anchorSpace=(Rectangle) worldSpace.clone();
//        anchorSpace.width-=screenSpace.width;
//        anchorSpace.height-=screenSpace.height;
        
        if (worldSpace.width > screenSpace.width) {
            anchorSpace.width -= screenSpace.width;
        } else {//当地图小于屏幕时,居中
            anchorSpace.width = 0;
            anchorSpace.x=-(screenSpace.width/2-worldSpace.width/2);
        }
        if (worldSpace.height > screenSpace.height) {
            anchorSpace.height -= screenSpace.height;
        } else {//当地图小于屏幕时,居中
            anchorSpace.height = 0;
            anchorSpace.y=-(screenSpace.height/2-worldSpace.height/2);
        }
        
        screenAnchor.x=0;
        screenAnchor.y=0;
        
        cursorAnchor.x=0;
        cursorAnchor.y=0;
        
        
    }
    public void showIsoCursor(Graphics2D g){
        int cw=cursor.getInfos()[0].src.width;
        int ch=cursor.getInfos()[0].src.height;

        Point p=stagMap_TilePlotter(cursorAnchor, cw, ch, dx, dy);
        cursor.put(g, p.x-screenAnchor.x, p.y-screenAnchor.y, 0);
    }
    @Override
    public void enter(GameCore entity) {
        super.enter(entity);
        
        Root r=(Root)entity;
        this.gameCore.getFrame().addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                super.keyPressed(e);
            }

            @Override
            public void keyReleased(KeyEvent e) {
                super.keyReleased(e);
            }

            @Override
            public void keyTyped(KeyEvent e) {
                super.keyTyped(e);
            }
        });
        
        this.mapWidth=r.mapWidth;
        this.mapHeight=r.mapheight;
        
        // load - setupSpaces - setupMap
        tileSet=new TileSet(0x000000);
        cursor=new TileSet(0x000000);
        
        try {
            tileSet.load("images/IsoHex12_3-1.bmp");
            cursor.load("images/IsoHex12_3-2.bmp");
            setupSpaces();
            setupMap();

            mmp = new MouseMap();
            loadMouseMap(mmp, "images/IsoHex5colors.bmp");
//            Point orgin = slideMap_TilePlotter(new Point(0, 0), tw, th, dx, dy);
//            orgin.x+=tileSet.getInfos()[0].dstExt.x;
//            orgin.y+=tileSet.getInfos()[0].dstExt.y;
//            mmp.refPt=orgin;
        } catch (IOException ex) {
            Logger.getLogger(StaggeredMapScene.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    public void showCursor(Graphics2D g){
        
    }
    public void drawMap(Graphics2D g){
        
        Point plot;
        Point map = new Point();
        tw=tileSet.tileInfos[0].src.width;
        th=tileSet.tileInfos[0].src.height;
        dx=this.gameCore.getFrame().getInsets().left;
        dy=this.gameCore.getFrame().getInsets().top;
        for(int r=0;r<this.mapHeight;r++){
            for(int c=0;c<this.mapWidth;c++){
                map.x=c;
                map.y=r;
                plot=stagMap_TilePlotter(map, tw,th,dx,dy);
                this.tileSet.put(g, plot.x-screenAnchor.x,
                        plot.y-screenAnchor.y, mapArr[c][r]);
            }
        }
    }
    @Override
    public synchronized void draw(Graphics2D g) {
        g.setColor(Color.WHITE);
        g.fill(screenSpace);
        drawMap(g);
        showIsoCursor(g);
        g.setColor(Color.RED);
//        g.draw(screenSpace);
        g.drawRect(screenSpace.x, screenSpace.y, screenSpace.width-1,
                screenSpace.height-1);
        g.setColor(Color.BLACK);
//        g.drawRect(anchorSpace.x, anchorSpace.y, anchorSpace.width-1,
//                anchorSpace.height-1);
    }

    @Override
    public void createGameActions() {
        System.out.println("create game action");
        NORTH=new GameAction("上");
        SOUTH=new GameAction("下");
        WEST=new GameAction("左");
        EAST=new GameAction("右");
        SPACE=new GameAction("空格");
        InputManager input=this.gameCore.getInputManager();
        input.mapToKey(NORTH,KeyEvent.VK_UP);
        input.mapToKey(EAST,KeyEvent.VK_RIGHT);
        input.mapToKey(SOUTH,KeyEvent.VK_DOWN);
        input.mapToKey(WEST,KeyEvent.VK_LEFT);
        input.mapToKey(SPACE,KeyEvent.VK_SPACE);
    }

    @Override
    public void createSystemActions() {
        super.createSystemActions();
//        throw new UnsupportedOperationException("Not supported yet.");
    }


    @Override
    public void checkSystemInput() {
        super.checkSystemInput();
        if(isEnterPressed()){
//            System.out.println("world space "+worldSpace);
//            System.out.println("screen space "+screenSpace);
//            System.out.println("anchor space "+anchorSpace);
        }
        if(pause.isPressed()){
            setPaused(!isPaused());
        }
    }
    public void checkScreenAnchor(){
        if(screenAnchor.x<anchorSpace.x) screenAnchor.x=anchorSpace.x;
        if(screenAnchor.x>anchorSpace.getMaxX()) screenAnchor.x=(int) anchorSpace.getMaxX();
        if(screenAnchor.y<anchorSpace.y) screenAnchor.y=anchorSpace.y;
        if(screenAnchor.y>anchorSpace.getMaxY()) screenAnchor.y=(int) anchorSpace.getMaxY();
    }
    @Override
    public synchronized void updateGame(long elapsedTime) {
        
        screenAnchor.x+=screenAnchorScroll.x;
        screenAnchor.y+=screenAnchorScroll.y;
        checkScreenAnchor();
        
        if(NORTH.isPressed() && EAST.isPressed()){
            System.out.println("右上");
            moveCursor(Direction.NORTHEAST);
        }else if(EAST.isPressed() && SOUTH.isPressed()){
            System.out.println("右下");
            moveCursor(Direction.SOUTHEAST);
        }else if(SOUTH.isPressed() && WEST.isPressed()){
            System.out.println("左下");
            moveCursor(Direction.SOUTHWEST);
        }else if(WEST.isPressed() && NORTH.isPressed()){
            System.out.println("左上");
            moveCursor(Direction.NORTHWEST);
        }else if(NORTH.isPressed()){
            System.out.println("上");
            moveCursor(Direction.NORTH);
        }else if(EAST.isPressed()){
            System.out.println("右");
            moveCursor(Direction.EAST);
        }else if(SOUTH.isPressed()){
            System.out.println("下");
            moveCursor(Direction.SOUTH);
        }else if(WEST.isPressed()){
//            Toolkit tk=Toolkit.getDefaultToolkit();
//             GraphicsConfiguration gc=this.gameCore.getScreenManager().graphicsConfiguration;
//             Rectangle r=gc.getBounds();
//              Insets i=tk.getScreenInsets(gc);
//            System.out.println(i);
            System.out.println("左");
            moveCursor(Direction.WEST);
        }
        if(isEnterPressed()){
            System.out.println("");
            System.out.println("enter:");
            Frame f=this.gameCore.getFrame();
            System.out.println("frame's insets:"+f.getInsets());
            Point p=new Point(this.gameCore.getInputManager().getMouseX(),
                    this.gameCore.getInputManager().getMouseY());
            System.out.println("mouse anchor[in frame] :"+p);
            Toolkit tk=InputManager.toolkit;
            Point point=MouseInfo.getPointerInfo().getLocation();
            System.out.println("screen point : "+point);
            SwingUtilities.convertPointFromScreen(point , 
                this.gameCore.getFrame() );
            System.out.println(""+point);
//            System.out.println("anchor space: "+anchorSpace);
//            System.out.println("world space: "+worldSpace);
            System.out.println("screen space: "+screenSpace);
            System.out.println("screen anchor: "+screenAnchor);
        }
        if(isMouseClick_button1()){
            System.out.println("");
            System.out.println("b1");
            

            
        }
        if(isbMouseClick_button3()){
            System.out.println("b3");
        }
    }
    public enum Direction{
        NORTH(0),NORTHEAST(1),EAST(2),SOUTHEAST(3),
        SOUTH(4),SOUTHWEST(5),WEST(6),NORTHWEST(7),CENTER(8);
        private final int num;
        Direction(int n){
            num=n;
        }
        public int getNum(){return num;}
    }
    public static void main(String[] args) throws IOException {
        int mapWidth=40;
        int mapHeight=80;
        TileSet tileSet=new TileSet(0x000000);
        tileSet.load("images/IsoHex12_2.bmp");
        Rectangle screenSpace=new Rectangle(0, 0, 640, 400);
        
        int tw=tileSet.tileInfos[0].src.width;
        int th=tileSet.tileInfos[0].src.height;
        Rectangle t1=(Rectangle) tileSet.tileInfos[0].dstExt.clone();
	Rectangle t2=(Rectangle) tileSet.tileInfos[0].dstExt.clone();
//	Point plot;
//        Point map=new Point(0, 0);
//        plot=slideMap_TilePlotter(map,tw,th);
//        t1.translate(plot.x, plot.y);
//        map=new Point(mapWidth-1, mapHeight-1);
//        plot=slideMap_TilePlotter(map,tw,th);
//        t2.translate(plot.x, plot.y);
//        Rectangle w=t1.union(t2);
//        System.out.println(t2);
//        System.out.println("w "+w);
    }
}
